﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;

namespace EasyStep.Business.Managers
{
    public class SessionManager : IDisposable
    {
        protected bool ReadOnly;
        protected bool RolledBack;
        public string ConnectionString;
        public ISession Session;
        private const string ConnectionConfigKey = "connection.connection_string";
        private static NHibernate.Cfg.Configuration configuration;
        private static Dictionary<string, ISessionFactory> sessionFactories;
        private static object sync = new object();

        public SessionManager(string connectionString, bool readOnly)
        {
            ReadOnly = readOnly;
            ConnectionString = connectionString;

            Session = CreateSession();
            
            if (!ReadOnly)
                Session.Transaction.Begin();            
        }

        protected virtual ISession CreateSession()
        {
            try
            {
                configuration = new NHibernate.Cfg.Configuration();
                configuration.Configure();

                sessionFactories = new Dictionary<string, ISessionFactory>();
            }
            catch (Exception ex)
            {
                throw new Exception("Could not configure NHibernate.", ex);
            }

            if (!sessionFactories.ContainsKey(ConnectionString))
            {
                lock (sync)
                {
                    if (!sessionFactories.ContainsKey(ConnectionString))
                    {
                        configuration.Properties[ConnectionConfigKey] = ConnectionString;
                        sessionFactories.Add(ConnectionString, configuration.BuildSessionFactory());
                    }
                }
            }

            ISession session = sessionFactories[ConnectionString].OpenSession();
            session.FlushMode = FlushMode.Commit;
            return session;
        }

        public void RollBack()
        {
            RolledBack = true;
        }

        #region IDisposable Members
        public void Dispose()
        {
            try
            {
                if (!ReadOnly)
                {
                    if (RolledBack)
                        Session.Transaction.Rollback();
                    else
                        Session.Transaction.Commit();
                }
            }
            finally
            {
                Session.Dispose();
            }
        }
        #endregion
    }
}